#include<iostream>
#include<memory>

//工厂创造具体产品时输入的参数
typedef enum   
{
    A,B
}ProductType;


//抽象产品类
class Product
{
    public:
        Product(){std::cout<<"Product constructor"<<std::endl;};
        ~Product(){std::cout<<"Product destructor"<<std::endl;};
        virtual void produce()const{};

};

//具体产品A
class ProductA:public Product
{
    public:
        ProductA(){std::cout<<"ProductA constructor"<<std::endl;};
        ~ProductA(){std::cout<<"ProductA destructor"<<std::endl;};
        void produce()const 
        {
            std::cout<<"我是产品 A"<<std::endl;
        }
};

//具体产品B
class ProductB:public Product
{
    public:
        ProductB(){std::cout<<"ProductB constructor"<<std::endl;};
        ~ProductB(){std::cout<<"ProductB destructor"<<std::endl;};
        void produce()const 
        {
            std::cout<<"我是产品 B"<<std::endl;
        }
};

//工厂类
class Factory
{
    public:
        Factory(){std::cout<<"Factory constructor"<<std::endl;};
        ~Factory(){std::cout<<"Factory destructor"<<std::endl;};

        std::shared_ptr<Product> CreateProduct(ProductType type)//面向客户的方法，生产对应的产品只需要输入对应的产品类型即可返回（生成）对应的产品
        {
            switch (type)
            {
            case A:
                return std::make_shared<ProductA>();
                break;
            case B:
                return std::make_shared<ProductB>();
                break;
            default:
                return nullptr;
                break;
            }
        }
    
};

//
ProductType WeNeedProtductA(){return ProductType::A;};
ProductType WeNeedProtductB(){return ProductType::B;};

int main(int argc, char const *argv[])
{
    //使用步骤1：构建工厂
    Factory factory;

    //使用步骤2：构建抽象产品(客户具体需要什么产品还不知道)
    std::shared_ptr<Product>product;

    //使用步骤3：客户打电话询问得知需要A类产品
    ProductType product_type = WeNeedProtductA();

    //使用步骤4：已经确定需要的具体产品，开始生产
    product = factory.CreateProduct(static_cast<ProductType>(product_type));

    //使用步骤5：客户已经得到想要的产品，开始投入使用
    product->produce();

    return 0;
}
